package com.xl.qa.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.xl.basic.entity.Result;
import com.xl.basic.entity.ResultEnums;
import com.xl.basic.entity.UserInfo;
import com.xl.basic.utils.JacksonUtils;
import com.xl.dao.domain.XlQuestionForm;
import com.xl.dao.mapper.XlQuestionFormMapper;
import com.xl.qa.enmus.QuestionTypeEnums;
import com.xl.qa.entity.param.AddOrUpdQuestionFormParam;
import com.xl.qa.service.QuestionFormService;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * @author 钟勇
 * Create in 2024/1/15 16:26
 */
@Service
@RequiredArgsConstructor
public class QuestionFormServiceImpl implements QuestionFormService {

    private final XlQuestionFormMapper questionFormMapper;

    @Override
    public Result<List<XlQuestionForm>> queryQuestionForm(@NonNull Integer questionId) {
        List<XlQuestionForm> list = questionFormMapper.selectList(new LambdaQueryWrapper<XlQuestionForm>()
                .eq(XlQuestionForm::getState, 1)
                .eq(XlQuestionForm::getQuestionId, questionId)
                .orderByAsc(XlQuestionForm::getSortIndex)
        );
        return ResultEnums.Success.getListResult(list);
    }

    @Override
    @Transactional(rollbackFor = Exception.class, timeout = 300)
    public Result<Object> addOrUpdQuestionForm(@NonNull AddOrUpdQuestionFormParam param, UserInfo operator) {
        String operatorUserId = operator != null ? operator.getUserId() : null;
        ObjectMapper objectMapper = JacksonUtils.objectMapper();

        //获取新的表单内容
        List<XlQuestionForm> rowList;
        try {
            rowList = objectMapper.readValue(param.getFormJsonStr(), new TypeReference<>() {
            });
        } catch (JsonProcessingException e) {
            return ResultEnums.Exception.getResult(e.toString());
        }

        //获取原来的表单内容
        Result<List<XlQuestionForm>> oriListRes = queryQuestionForm(param.getQuestionId());
        if (oriListRes.isErr()) {
            return oriListRes.create();
        }

        List<XlQuestionForm> oriRowList = oriListRes.getResult();
        if (oriRowList == null) {
            oriRowList = new ArrayList<>();
        }
        List<Integer> oriRowIdList = oriRowList.stream()
                .map(XlQuestionForm::getRowId)
                .toList();

        //所有更新的表单内容
        List<XlQuestionForm> addRowList = new ArrayList<>();
        List<Integer> rowIdList = new ArrayList<>();

        rowList.forEach(item -> {
            if (item.getRowId() == null) {
                item.setQuestionId(param.getQuestionId())
                        .setState(1)
                        .setAddTime(LocalDateTime.now())
                        .setAddUser(operatorUserId);
                addRowList.add(item);
            } else {
                rowIdList.add(item.getRowId());
            }
        });

        Result<Object> addRowValidatorRes = validatorFormRow(addRowList);
        if (addRowValidatorRes.isErr()) {
            return addRowValidatorRes;
        }

        //所有删除的表单id集合
        List<Integer> delRowIdList = oriRowIdList.stream()
                .filter(rowId -> !rowIdList.contains(rowId))
                .toList();

        //所有更新的表单内容
        List<XlQuestionForm> updRowList = rowList.stream().filter(
                //不是删除的，并且不是新增的，并且在旧的表单中有的
                item -> oriRowIdList.contains(item.getRowId())
                        && !delRowIdList.contains(item.getRowId())
                        && !addRowList.contains(item)

        ).map(
                item -> item.setState(1)
                        .setUpdTime(LocalDateTime.now())
                        .setUpdUser(operatorUserId)
        ).toList();


        Result<Object> updRowValidatorRes = validatorFormRow(updRowList);
        if (updRowValidatorRes.isErr()) {
            return updRowValidatorRes;
        }

        if (!delRowIdList.isEmpty()) {
            int update = questionFormMapper.update(new XlQuestionForm().setState(0)
                            .setUpdTime(LocalDateTime.now())
                            .setUpdUser(operatorUserId),
                    new LambdaQueryWrapper<XlQuestionForm>()
                            .eq(XlQuestionForm::getState, 1)
                            .in(XlQuestionForm::getQuestionId, delRowIdList)
            );
            if (update == 0) {
                return ResultEnums.Exception.getResult("表字段删除失败");
            }
        }

        if (!updRowList.isEmpty()) {
            for (XlQuestionForm data : updRowList) {
                if (questionFormMapper.updateById(data) == 0) {
                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                    return ResultEnums.Exception.getResult("表字段编辑失败");
                }
            }
        }

        if (!addRowList.isEmpty()) {
            for (XlQuestionForm data : addRowList) {
                if (questionFormMapper.insert(data) == 0) {
                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                    return ResultEnums.Exception.getResult("表字段新增失败");
                }
            }
        }

        return ResultEnums.Success.getResult();
    }

    private Result<Object> validatorFormRow(@NonNull List<XlQuestionForm> list) {
        for (XlQuestionForm row : list) {
            if (StrUtil.isBlank(row.getRowTitle())) {
                return ResultEnums.ParamError.getResult("标题不能为空");
            }

            if (row.getRowType() == null) {
                return ResultEnums.ParamError.getResult("数据类型不能为空");
            }

            QuestionTypeEnums questionTypeEnums = QuestionTypeEnums.getByType(row.getRowType());
            if (questionTypeEnums == null) {
                return ResultEnums.ParamError.getResult("不支持的数据类型");
            }

            if (questionTypeEnums.getScopeFlag().equals(1) && StrUtil.isBlank(row.getRowScope())) {
                return ResultEnums.ParamError.getResult("数据类型需要行值域");
            }
        }

        return ResultEnums.Success.getResult();
    }
}
